#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> 
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <openssl/sha.h>  
#include "socket_thread.h"
#include "timet.h"
#include "main.h"
#include "usr_cfg.h"
#include "daq_thread.h"
#include "adc_spd_uio.h"
#include "file_save.h"
#include "socket_sub_thread.h"
#include "led_gpio_ctl.h"
#include "usr_typedef.h"
#include "afe_cmd.h"
#include "zlog.h"
#include "json.h"


extern thread_status state_acc_daq;
extern pthread_mutex_t afe_data_mutex;
extern afe_dev_info afe1_dev;


#define TCP_REV_CMDS_HEAD				0xAAAA				//$
#define TCP_REV_CMDS_TAIL				0xBBBB				//!
#define TCP_REV_CMDS_LEN				16	

#define TCP_RTN_CMDS_HEAD				"#AA#"
#define TCP_RTN_CMDS_TAIL				"*55*"
#define TCP_RTN_CMDS_LEN				24


static uint32_t file_info_head_len 		= sizeof(file_info_head);		//定义头长度--128byte
static uint32_t file_info_chx_len 		= sizeof(file_info_chx);		//定义头长度--128byte
static uint32_t file_td_calc_norl_len	= sizeof(td_calc_norl);			//定义时域特征值长度--64byte
static uint32_t file_info_spd_len 		= sizeof(file_info_spd);		//定义头长度--32byte
static uint32_t data_framd_info_len 	= sizeof(data_frame_len_info);	//定义数据帧长度信息长度--40byte


//TCP接收命令表
const char *rev_cmds_list[] = {   					// 指针类型命令结构
	"$SET ACQ  START!",								// cmd0(开始采集命令)
	"$SET ACQ   STOP!",								// cmd1(停止采集命令)
	"$SET TIB  START!",								// cmd2(开始测试命令)
	"$SET TIB   STOP!",								// cmd3(停止测试命令)
	"$SET DEV REBOOT!",								// cmd4(设备重启)
	"$GET HEART BEAT!",								// cmd5(心跳命令)
	"$SET TIM UPDATE!",								// cmd6(设备时间设置)
	"$SET CFG UPDATE!",								// cmd7(更新配置)
	"$GET CFG   INFO!",								// cmd8(获取配置)
	"$GET RAW WAV  0!",								// cmd9(振动通道0原始数据以及特征值上传)
	"$GET RAW WAV  1!",								// cmd10(振动通道1原始数据以及特征值上传)
	"$GET RAW WAV  2!",								// cmd11(振动通道2原始数据以及特征值上传)
	"$GET RAW WAV  3!",								// cmd12(振动通道3原始数据以及特征值上传)
	"$GET RAW WAV  4!",								// cmd13(振动通道4原始数据以及特征值上传)
	"$GET RAW WAV  5!", 							// cmd14(振动通道5原始数据以及特征值上传)
	"$GET RAW WAV  6!", 							// cmd15(振动通道6原始数据以及特征值上传)
	"$GET RAW WAV  7!", 							// cmd16(振动通道7原始数据以及特征值上传)
	"$GET RAW WAV  8!", 							// cmd17(振动通道8原始数据以及特征值上传)
	"$GET RAW WAV  9!", 							// cmd18(振动通道9原始数据以及特征值上传)
	"$GET RAW WAV 10!", 							// cmd19(振动通道10原始数据以及特征值上传)
	"$GET RAW WAV 11!", 							// cmd20(振动通道11原始数据以及特征值上传)
	"$GET RAW WAV 12!", 							// cmd21(振动通道12原始数据以及特征值上传)
	"$GET RAW WAV 13!", 							// cmd22(振动通道13原始数据以及特征值上传)
	"$GET RAW WAV 14!", 							// cmd23(振动通道14原始数据以及特征值上传)
	"$GET RAW WAV 15!", 							// cmd24(振动通道15原始数据以及特征值上传)
	"$GET RAW WAV S0!",								// cmd25(转速通道0原始数据上传)
	"$GET RAW WAV S1!",								// cmd26(转速通道1原始数据上传)
	"$GET ALL STATUS!",								// cmd27(所有通道状态)
	"$GET DEV   INFO!",								// cmd28(设备基本信息)
	"$GET ALL A DATA!",								// cmd29(加速度所有通道数据)
	"$SET DISK1  CLR!",								// cmd30(清空硬盘1数据)
	"$SET DISK2  CLR!",								// cmd31(清空硬盘2数据)
	"$SET EMMC   CLR!",								// cmd32(清空eMMC数据)
	"$GET RSV   INFO!"								// cmd33(预留信息)
};
	
static uint32_t rev_cmds_list_len = sizeof(rev_cmds_list) / sizeof(rev_cmds_list[0]);
static int socket_timeout_recv(int fd, char *buf, int len);
static int socket_timeout_send(int fd, char *buf, int len);



//命令检索函数
int cmds_index_of(char *strin, const char *cmds[], int size)
{
	int i = 0;

	/*
		strstr函数用于判断字符串str2是否为字符串str1的子串，
		如果是函数返回str2在str1中首次出现的地址，否则返回NULL。
	*/

	//if(strstr(strin, "$RTC ") != NULL)	//RTC命令直接返回
	//	return 6;

	/*	strcmp() 函数用于对两个字符串进行比较（区分大小写）
		strcmp() 会根据 ASCII 编码依次比较 str1 和 str2 的每一个字符，
		直到出现不到的字符，或者到达字符串末尾（遇见\0）
	*/
	while (i < size) 
	{
		if (strcmp(strin, cmds[i]) == 0)
			return i;
		i++;
	}
	
	return -1;
}

//加速度通道号检索函数
static int32_t get_chx_index_from_cmds(const char cmds[])
{
	int32_t chx_index;

	chx_index = atoi(cmds + TCP_REV_CMDS_LEN - 3);
	if(chx_index > ACC_CH_TOTAL || chx_index < 0)
		chx_index = 0;

	return chx_index;
}


//转速通道号检索函数
static int32_t get_spd_index_from_cmds(const char cmds[])
{
	int32_t chx_index;

	chx_index = atoi(cmds + TCP_REV_CMDS_LEN - 2);
	if(chx_index > SPD_CH_TOTAL || chx_index < 0)
		chx_index = 0;

	return chx_index;
}



//所有通道状态发送包括文件头、通道头、特征值等
static void all_channels_state_send(socket_info *s, const sys_cfg_info *sys, const chx_cfg_info chx[], 
		 				const acc_unit acc[], const spd_cfg_info cspd[], const spd_unit uspd[], sys_runtime *rt)
{
	uint8_t ch, chx_num, spd_num;
	uint32_t chk = 0;
	file_info_head fhead;
	file_info_chx  chead;
	file_info_spd  shead;
	uint32_t file_total_len = 0;

	data_frame_len_info frame_len;

	file_fill_file_head_format(&fhead, sys, chx, uspd, rt);
	chx_num = enable_chx_num(chx);
	spd_num = enable_spd_num(cspd);
	file_total_len = 4 + 4 + data_framd_info_len + file_info_head_len + file_info_chx_len * chx_num
					+ file_td_calc_norl_len * chx_num + file_info_spd_len * spd_num + 0 + 32 + 4;

	frame_len.file_info_len 	= file_info_head_len;
	frame_len.file_info_code	= DATA_FRAME_FILE_INFO_CODE;
	frame_len.chx_head_len 		= file_info_chx_len * chx_num;
	frame_len.chx_head_code		= DATA_FRAME_CHX_HEAD_CODE;
	frame_len.eigen_data_len 	= file_td_calc_norl_len * chx_num;
	frame_len.eigen_data_code	= DATA_FRAME_EIGEN_DATA_CODE;
	frame_len.raw_data_len 		= 0;
	frame_len.raw_data_code		= DATA_FRAME_RAW_DATA_CODE;
	frame_len.resv_data_len 	= 0;
	frame_len.resv_data_code	= DATA_FRAME_RESV_DATA_CODE;


	switch (sys->duration)
	{
		case 1 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
			break;
		case 2 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA2, 4);
			break;
		case 5 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA5, 4);
			break;
		case 10 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEAA, 4);
			break;
		default :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
	}

	chk += socket_timeout_send(s->new_fd, COMM_PROTOCOL_VERSION, 4);
	chk += socket_timeout_send(s->new_fd, (char *)&frame_len, data_framd_info_len);
	chk += socket_timeout_send(s->new_fd, (char *)&fhead, file_info_head_len);

	pthread_mutex_lock(&afe_data_mutex);
	for(ch = 0; ch < ACC_CH_TOTAL; ch++) {
		file_fill_chx_data_format(&chead, ch, chx);
		chk += socket_timeout_send(s->new_fd, (char *)&chead, file_info_chx_len);
		chk += socket_timeout_send(s->new_fd, (char *)&acc[ch].td_eigen_value, file_td_calc_norl_len);
	}
	pthread_mutex_unlock(&afe_data_mutex);

	for(ch = 0; ch < SPD_CH_TOTAL; ch++) {
		file_fill_spd_data_format(&shead, ch, cspd);
		chk += socket_timeout_send(s->new_fd, (char *)&shead, file_info_spd_len);
	}
	
	chk += socket_timeout_send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4);

	if(chk != file_total_len) {
		dzlog_error("socket function all_channels_state_send() error！check is %d", chk);
		printf("socket function all_channels_state_send() error！check is %d\n", chk); 
		s->status = TS_TERMINATED;
		pthread_exit((void *)1);
	}
}

//加速度单通道数据发送包括文件头、通道头、特征值、原始数据、时域角域的冲击包络等
static void vib_single_channel_data_send(socket_info *s, uint8_t index, const sys_cfg_info *sys, 
			 			const spd_unit spd[], const chx_cfg_info chx[], const acc_unit acc[], sys_runtime *rt)
{
	uint32_t chk = 0;
	uint32_t raw_g_len;
	uint8_t sha256_digest[32];
	uint32_t file_total_len = 0;

	data_frame_len_info frame_len;
	file_info_head fhead;
	file_info_chx  chead;

	file_fill_file_head_format(&fhead, sys, chx, spd, rt);
	file_fill_chx_data_format(&chead, index, chx);

	raw_g_len = sys->duration * sys->samp_freq * sizeof(float);
	file_total_len = 4 + 4 + data_framd_info_len + file_info_head_len + file_info_chx_len 
			+ file_td_calc_norl_len + raw_g_len + 0 + 32 + 4;

	frame_len.file_info_len 	= file_info_head_len;
	frame_len.file_info_code	= DATA_FRAME_FILE_INFO_CODE;
	frame_len.chx_head_len 		= file_info_chx_len;
	frame_len.chx_head_code		= DATA_FRAME_CHX_HEAD_CODE;
	frame_len.eigen_data_len 	= file_td_calc_norl_len;
	frame_len.eigen_data_code	= DATA_FRAME_EIGEN_DATA_CODE;
	frame_len.raw_data_len 		= raw_g_len;
	frame_len.raw_data_code		= DATA_FRAME_RAW_DATA_CODE;
	frame_len.resv_data_len 	= 0;
	frame_len.resv_data_code	= DATA_FRAME_RESV_DATA_CODE;

	switch (sys->duration)
	{
		case 1 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
			break;
		case 2 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA2, 4);
			break;
		case 5 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA5, 4);
			break;
		case 10 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEAA, 4);
			break;
		default :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
	}
	
	chk += socket_timeout_send(s->new_fd, COMM_PROTOCOL_VERSION, 4);
	chk += socket_timeout_send(s->new_fd, (char *)&frame_len, data_framd_info_len);
	chk += socket_timeout_send(s->new_fd, (char *)&fhead, file_info_head_len);
	chk += socket_timeout_send(s->new_fd, (char *)&chead, file_info_chx_len);
	
	pthread_mutex_lock(&afe_data_mutex);
	//发送特征值
	chk += socket_timeout_send(s->new_fd, (char *)&acc[index].td_eigen_value, sizeof(td_calc_norl));
	//发送原始数据
	chk += socket_timeout_send(s->new_fd, (char *)acc[index].td_vdata_raw_g, raw_g_len);
	//原始数据校验值
	SHA256((uint8_t *)acc[index].td_vdata_raw_g, raw_g_len, sha256_digest);
	chk += socket_timeout_send(s->new_fd, (char *)sha256_digest, 32);
	
	pthread_mutex_unlock(&afe_data_mutex);
	
	chk += socket_timeout_send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4);
	
	if (chk != file_total_len) {
		dzlog_error("socket function single_channel_data_send() error！check is %d", chk);
		printf("socket function single_channel_data_send() error！check is %d\n", chk); 
		s->status = TS_TERMINATED;
		pthread_exit((void *)1);
	}
}


//速度通道数据发送包括文件头、通道头、原始数据等
static void speed_channel_data_send(socket_info *s, uint8_t index, const sys_cfg_info *sys, 
				const chx_cfg_info chx[], const spd_cfg_info *cspd, const spd_unit uspd[], sys_runtime *rt)
{
	uint32_t chk = 0;
	uint32_t spd_raw_len;
	uint32_t file_total_len = 0;

	data_frame_len_info frame_len;
	file_info_head fhead;
	file_info_spd  shead;

	spd_raw_len = sys->samp_freq * sys->duration * sizeof(uint32_t);

	//文件头中已包含转速信息
	file_fill_file_head_format(&fhead, sys, chx, uspd, rt);
	file_total_len = 4 + 4 + data_framd_info_len + file_info_head_len + file_info_spd_len
					 + spd_raw_len + 0 + 4;

	frame_len.file_info_len 	= file_info_head_len;
	frame_len.file_info_code	= DATA_FRAME_FILE_INFO_CODE;
	frame_len.chx_head_len 		= file_info_spd_len;
	frame_len.chx_head_code		= DATA_FRAME_CHX_HEAD_CODE;
	frame_len.eigen_data_len 	= 0;
	frame_len.eigen_data_code	= DATA_FRAME_EIGEN_DATA_CODE;
	frame_len.raw_data_len 		= spd_raw_len;
	frame_len.raw_data_code		= DATA_FRAME_RAW_DATA_CODE;
	frame_len.resv_data_len 	= 0;
	frame_len.resv_data_code	= DATA_FRAME_RESV_DATA_CODE;

	switch (sys->duration)
	{
		case 1 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
			break;
		case 2 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA2, 4);
			break;
		case 5 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA5, 4);
			break;
		case 10 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEAA, 4);
			break;
		default :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
	}

	chk += socket_timeout_send(s->new_fd, COMM_PROTOCOL_VERSION, 4);
	chk += socket_timeout_send(s->new_fd, (char *)&frame_len, data_framd_info_len);
	chk += socket_timeout_send(s->new_fd, (char *)&fhead, file_info_head_len);
	file_fill_spd_data_format(&shead, index, cspd);
	chk += socket_timeout_send(s->new_fd, (char *)&shead, file_info_spd_len);
	chk += socket_timeout_send(s->new_fd, (char *)uspd[index].speed_pulse_raw, spd_raw_len);
	chk += socket_timeout_send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4);

	if(chk != file_total_len) {
		dzlog_error("socket function speed_channel_data_send() error！check is %d", chk);
		printf("socket function speed_channel_data_send() error！check is %d\n", chk); 
		s->status = TS_TERMINATED;
		pthread_exit((void *)1);
	}
}

//所有通道数据顺序发送，包括文件头、通道头、特征值、原始数据、时域角域的冲击包络等
static void all_channel_data_send(socket_info *s, const sys_cfg_info *sys, const spd_unit spd[], 
				 const chx_cfg_info chx[], const acc_unit acc[], const spd_cfg_info *cspd, sys_runtime *rt)
{
	uint8_t ch;
	uint32_t chk = 0;
	uint32_t raw_g_len;
	uint8_t sha256_digest[32];
	uint8_t sha256_temp[32 * ACC_CH_TOTAL];
	uint8_t sha256_ch = 0;
	uint32_t file_total_len = 0;
	uint8_t chx_num;

	data_frame_len_info frame_len;
	file_info_head fhead;
	file_info_chx  chead;
	//file_info_spd  shead;

	file_fill_file_head_format(&fhead, sys, chx, spd, rt);
	raw_g_len = sys->duration * sys->samp_freq * sizeof(float);
	chx_num = enable_chx_num(chx);
	
	file_total_len = 4 + 4 + data_framd_info_len + file_info_head_len + file_info_chx_len * chx_num
			+ file_td_calc_norl_len * chx_num + raw_g_len * chx_num + 0 + 32 + 4;

	frame_len.file_info_len 	= file_info_head_len;
	frame_len.file_info_code	= DATA_FRAME_FILE_INFO_CODE;
	frame_len.chx_head_len 		= file_info_chx_len * chx_num;
	frame_len.chx_head_code		= DATA_FRAME_CHX_HEAD_CODE;
	frame_len.eigen_data_len 	= file_td_calc_norl_len * chx_num;
	frame_len.eigen_data_code	= DATA_FRAME_EIGEN_DATA_CODE;
	frame_len.raw_data_len 		= raw_g_len * chx_num;
	frame_len.raw_data_code		= DATA_FRAME_RAW_DATA_CODE;
	frame_len.resv_data_len 	= 0;
	frame_len.resv_data_code	= DATA_FRAME_RESV_DATA_CODE;

	
	switch (sys->duration)
	{
		case 1 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
			break;
		case 2 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA2, 4);
			break;
		case 5 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA5, 4);
			break;
		case 10 :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEAA, 4);
			break;
		default :
			chk += socket_timeout_send(s->new_fd, SAVE_FILE_HEAD_TYPEA1, 4);
	}

	chk += socket_timeout_send(s->new_fd, COMM_PROTOCOL_VERSION, 4);
	chk += socket_timeout_send(s->new_fd, (char *)&frame_len, data_framd_info_len);
	chk += socket_timeout_send(s->new_fd, (char *)&fhead, file_info_head_len);

	for (ch = 0; ch < ACC_CH_TOTAL; ch++) {
		if (chx[ch].chx_en == ON) {
			file_fill_chx_data_format(&chead, ch, chx);
			chk += socket_timeout_send(s->new_fd, (char *)&chead, file_info_chx_len);
			pthread_mutex_lock(&afe_data_mutex);
			//发送特征值
			chk += socket_timeout_send(s->new_fd, (char *)&acc[ch].td_eigen_value, file_td_calc_norl_len);
			//发送原始数据
			chk += socket_timeout_send(s->new_fd, (char *)acc[ch].td_vdata_raw_g, raw_g_len);	
			//原始数据校验值计算
			SHA256((unsigned char *)acc[ch].td_vdata_raw_g, raw_g_len, &sha256_temp[32 * sha256_ch++]);
			pthread_mutex_unlock(&afe_data_mutex);
		}
	}

	/*
	for (ch = 0; ch < SPD_CH_TOTAL; ch++) {
		if (cspd[ch].spd_en == ON) {
			file_fill_spd_data_format(&shead, ch, cspd);
			chk += socket_timeout_send(s->new_fd, (char *)&shead, file_info_spd_len);
		}
	}*/
	
	SHA256(sha256_temp, 32 * sha256_ch, sha256_digest);
	chk += socket_timeout_send(s->new_fd, (char *)sha256_digest, 32);
	chk += socket_timeout_send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4);

	if (chk != file_total_len) {
		dzlog_error("socket function all_channel_data_send() error！check is %d", chk);
		printf("socket function all_channel_data_send() error！check is %d\n", chk); 
		s->status = TS_TERMINATED;
		pthread_exit((void *)1);
	}
}


//技术支持信息发送
void techical_support_info_send(socket_info *s)
{
	uint32_t chk = 0;

	chk += (send(s->new_fd, SAVE_FILE_HEAD_TYPEA0, 4, 0) < 0) ? 1 : 0;

	chk += (send(s->new_fd, TCP_SPLIT_LINE1, sizeof(TCP_SPLIT_LINE1), 0) < 0) ? 1 : 0;
	chk += (send(s->new_fd, TCP_COMPANY_INFO, sizeof(TCP_COMPANY_INFO), 0) < 0) ? 1 : 0;
	chk += (send(s->new_fd, TCP_TEL_CONTACT_INFO, sizeof(TCP_TEL_CONTACT_INFO), 0) < 0) ? 1 : 0;
	chk += (send(s->new_fd, TCP_EMAIL_CONTACT_INFO, sizeof(TCP_EMAIL_CONTACT_INFO), 0) < 0) ? 1 : 0;
	chk += (send(s->new_fd, TCP_SPLIT_LINE2, sizeof(TCP_SPLIT_LINE2), 0) < 0) ? 1 : 0;

	chk += (send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4, 0) < 0) ? 1 : 0;

	if(chk != 0) {
		dzlog_error("socket function techical_support_info_send() send error！check is %d", chk);
		printf("socket function techical_support_info_send() send error！check is %d\n", chk); 
		s->status = TS_TERMINATED;
		pthread_exit((void *)1);
	}
}


//设备基本信息发送即文件头发送
static void device_basic_info_send(socket_info *s, const sys_cfg_info *sys, 
							const chx_cfg_info chx[], const spd_unit uspd[], sys_runtime *rt)
{
	uint8_t chk = 0;

	file_info_head fhead;
	
	file_fill_file_head_format(&fhead, sys, chx, uspd, rt);

	chk += (send(s->new_fd, SAVE_FILE_HEAD_TYPEA0, 4, 0) < 0) ? 1 : 0;
	chk += (send(s->new_fd, (char *)&fhead, file_info_head_len, 0) < 0) ? 1 : 0;
	chk += (send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4, 0) < 0) ? 1 : 0;

	if(chk != 0) {
		dzlog_error("socket function device_basic_info_send() send error！check is %d", chk);
		printf("socket function device_basic_info_send() send error！check is %d\n", chk);
		s->status = TS_TERMINATED;
		pthread_exit((void *)1);
	}
}


static void acq_start_cmd_exec(void)
{
	int irq_on = 1;

	//afe_acq_begin(&afe1_dev);
	//usleep(20000);

	adc_axi_reg_set(&adc_dev, ADS1672_REG1_OFFSET, 0x00);   		
	usleep(10000);			
	adc_axi_reg_set(&adc_dev, ADS1672_REG1_OFFSET, 0x01);			// 即是复位也是同步
	usleep(10000);													// 应保证至少1ms
	
	write(adc_dev.adc_axi_uio_fd, &irq_on, 0x04);   				// 从新开始UIO中断 必须
	adc_axi_reg_set(&adc_dev, ADS1672_REG0_OFFSET, 0xFF); 			// 非连续采集需要从新开始
	state_acc_daq.status = TS_ALIVE;
	led_daq_in_process();

	dzlog_notice("acq_start_cmd_exec() start from socket cmd!");
}

static void acq_stop_cmd_exec(void)
{
	adc_axi_reg_set(&adc_dev, ADS1672_REG0_OFFSET, 0x00);   		// 停止采集
	usleep(100);
	// afe_acq_stop(&afe1_dev);
	// usleep(1000);

	state_acc_daq.status = TS_READY;
	dzlog_notice("acq_start_cmd_exec() stop from socket cmd!");
}


static void tib_start_cmd_exec(void)
{
	afe_tib_begin(&afe1_dev);	// 前端FPGA只是开启了正弦波，通电还需要开始采集
	usleep(1000);

	dzlog_notice("tib_start_cmd_exec() start from socket cmd!");
}

static void tib_stop_cmd_exec(void)
{
	afe_tib_stop(&afe1_dev);
	usleep(1000);

	dzlog_notice("tib_start_cmd_exec() stop from socket cmd!");
}


//RTC时钟同步命令解析
static void socket_rtc_cmd_parse(socket_info *s, char *cmd)
{
	char date_cmd[30] = "date -s \"2023-10-10 20:08:08\"";
	strncpy(&date_cmd[9], cmd, 19);
	
	if (sys_cfg.debug == ON)
		printf("date cmd is %s, socket cmd is %s\n", date_cmd, cmd);
	
	system(date_cmd);			//系统时间同步
	system("hwclock -w");		//同步时间写入硬件RTC

	send(s->new_fd, "#AA#OK!*55*", 11, 0);				//成功执行命令则发回命令字符
	dzlog_notice("rtc update from socket cmd!");
}

/*
static void system_poweroff_cmd_exec(void)
{
	system("sync");	
	sleep(1);
	system("poweroff");
}
*/

static void system_reboot_cmd_exec(void)
{
	system("sync");	
	sleep(1);
	system("reboot");
}

static void system_heartbeat_cmd_exec(socket_info *s)
{
	char rtc[20] = "2023-10-10 20:08:08";
	// 发送当前RTC时间
	get_time_str_fixed_format2(rtc);
	socket_timeout_send(s->new_fd, rtc, SOCKET_RTC_TIME_LEN);
}

static void disk_vdata_clear(char *path)
{
	char clear_cmd[50];
	sprintf(clear_cmd, "%s%s%s", "rm -r ", path, "*");
	system(clear_cmd);
	dzlog_notice("fifo buffer command %s executed!!!", clear_cmd);
}


static void socket_json_cfg_file_resv(socket_info *s, const char *srcfile, uint32_t len)
{
	FILE *fp;

	if (remove(JSON_CONFIG_FILE_BACKUP) == 0)
	{
		system("sync");
		usleep(1000);
		if (rename(JSON_CONFIG_FILE, JSON_CONFIG_FILE_BACKUP) == 0)
		{
			fp = fopen(JSON_CONFIG_FILE, "w+");
			fwrite(srcfile, sizeof(char), len, fp);
			system("sync");
			fclose(fp);
			send(s->new_fd, "#AA#OK!*55*", 11, 0);				//成功执行命令则发回命令字符
			usleep(1000);
			exit(EXIT_SUCCESS);
		} else {
			printf("json config file rename failed!\n");
			dzlog_error("json config file rename failed!");
		}
	} else {
		fp = fopen(JSON_CONFIG_FILE_BACKUP, "a+");				//没有创建一个空的配置
		system("sync");
		fclose(fp);
		printf("backup json config file remove failed!\n");
		dzlog_error("backup json config file remove failed!");
	}
}


static void socket_json_cfg_with_fd_file_send(socket_info *s, const char *srcfile)
{
	uint32_t chk = 0;
	char filename[JSON_CONFIG_PATH_MAX];
	uint32_t file_total_len = 0;
	json_cfg_file_info 	cfg_file_info;
	
	(void)snprintf(filename, sizeof(filename), "%s", srcfile);

	int fd = open(filename, O_RDWR, 0);
	if (fd < 0)
	{
		fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));
		dzlog_error("FAIL: unable to open %s: %s", filename, strerror(errno));
		exit(EXIT_FAILURE);
	}
	assert(NULL == json_object_from_fd_ex(fd, -2));

    (void)lseek(fd, SEEK_SET, 0);
	
	json_object *jso = json_object_from_fd_ex(fd, 10);
	if (jso != NULL) {
		printf("OK: json_object_from_fd_ex(valid_nested.json, 10) socket send\n");
		cfg_file_info.cfg_rsv_string  = NULL;
		cfg_file_info.cfg_data_offset = 16;
		cfg_file_info.cfg_data_string = json_object_to_json_string(jso);
		cfg_file_info.cfg_data_len = strlen(cfg_file_info.cfg_data_string);	// 先发送配置文件长度4字节
		SHA256((uint8_t *)cfg_file_info.cfg_data_string, 32, cfg_file_info.cfg_data_sha256);
		file_total_len = 4 + 4 + 4 + 4 + 0 + cfg_file_info.cfg_data_len + 32 + 4;
		
		chk += socket_timeout_send(s->new_fd, CFG_FILE_HEAD_TYPEC0, 4);
		chk += socket_timeout_send(s->new_fd, JSON_CFG_PROTOCOL_VERSION, 4);
		chk += socket_timeout_send(s->new_fd, (char *)&cfg_file_info.cfg_data_offset, sizeof(cfg_file_info.cfg_data_offset));
		chk += socket_timeout_send(s->new_fd, (char *)&cfg_file_info.cfg_data_len, sizeof(cfg_file_info.cfg_data_len));	
		chk += socket_timeout_send(s->new_fd, (char *)cfg_file_info.cfg_data_string, cfg_file_info.cfg_data_len); 
		chk += socket_timeout_send(s->new_fd, (char *)cfg_file_info.cfg_data_sha256, 32);
		chk += socket_timeout_send(s->new_fd, SAVE_FILE_TAIL_CYHK, 4);
		
		if (chk != file_total_len)	// 发送长度与实际不符
		{
			dzlog_error("socket function json config file send error！");
			printf("socket function json config file send error！\n"); 
			s->status = TS_TERMINATED;
			pthread_exit((void *)1);
		}
	} else {
		fprintf(stderr, "FAIL: unable to parse contents of %s: %s\n", filename,
		        json_util_get_last_err());
		dzlog_error("FAIL: unable to parse contents of %s: %s", filename, 
				 json_util_get_last_err());
	}
	close(fd);
}



static int socket_timeout_recv(int fd, char *buf, int len)
{
	int recv_ret;
	int ret;
	
    recv_ret = recv(fd, buf, len, 0);

	if (recv_ret == 0) {											//0为已经断开连接
		perror("socket recv socket is closed! recv() return \n");
		dzlog_warn("socket recv : socket is closed! recv() return %d", recv_ret);
		ret = SOCKET_CLOSE_ERR;
	} else if (recv_ret < 0) {
		if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
		{
			// perror("socket recv usr cmds timeout! recv() return \n");
			// dzlog_warn("socket recv usr cmds timeout! recv() return %d", recv_ret);
			ret = SOCKET_TIMEOUT_ERR;
		} else {
			perror("socket recv usr cmds error! recv() return \n");	//-1为接收错误
			dzlog_error("socket recv : usr cmds error! recv() return %d, errno is %s", recv_ret, strerror(errno));
			ret = SOCKET_OTHERS_ERR;
		}
	} else
		ret = recv_ret;

    return ret;
}


static int socket_timeout_send(int fd, char *buf, int len)
{
	int send_ret;
	int ret;
	
    send_ret = send(fd, buf, len, 0);

	if (send_ret == 0) {												//0为已经断开连接
		perror("socket send : socket is closed! send() return \n");
		dzlog_warn("socket send : socket is closed! send() return %d", send_ret);
		ret = SOCKET_CLOSE_ERR;
	} else if (send_ret < 0) {
		if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
		{
			perror("socket send usr data timeout! send() return \n");
			dzlog_warn("socket send usr data timeout! send() return %d, errno is %s", send_ret, strerror(errno));
			ret = SOCKET_TIMEOUT_ERR;
		} else {
			perror("socket send usr data error! send() return \n");	//-1为接收错误
			dzlog_error("socket send : usr data error! send() return %d, errno is %s", send_ret, strerror(errno));
			ret = SOCKET_OTHERS_ERR;
		}
	} else 
		ret = send_ret;

    return ret;
}



//tcp server子线程
void* socket_sub_thread(void* arc) 
{
	int new_fd, swc, recv_ret;
	uint8_t chx_index;
	socket_info *s = NULL;
	char usr_cmds[24] = "";
	char rtn_code[24] = "";
	char rtc_cmds[24] = "";
	uint32_t cfg_file_len = 0;
	uint32_t cfg_file_offset = 0;
	uint32_t recv_file_len = 0;

	if (arc == NULL) {
		dzlog_error("sub socket thread input parameter error");
		printf("sub socket thread input parameter error\n"); 
	}
	
	s = (socket_info*)arc;
	new_fd = s->new_fd;

	while(1) {
		memset(usr_cmds, 0x00, sizeof(usr_cmds));
		recv_ret = socket_timeout_recv(new_fd, usr_cmds, TCP_REV_CMDS_LEN);
		if (recv_ret == SOCKET_TIMEOUT_ERR) {
			continue;
		} else if ((recv_ret == SOCKET_CLOSE_ERR) ||  (recv_ret == SOCKET_OTHERS_ERR)) { 
			break;
		} else {
			swc = cmds_index_of(usr_cmds, rev_cmds_list, rev_cmds_list_len);
			if (swc >= 0) {
				sprintf(rtn_code, "%s%s%s", TCP_RTN_CMDS_HEAD, rev_cmds_list[swc], TCP_RTN_CMDS_TAIL);
				send(new_fd, rtn_code, TCP_RTN_CMDS_LEN, 0);			//成功接收命令则发回命令字符
			} else {
				send(new_fd, "#AA#$CMD ERR 100000!*55*", TCP_RTN_CMDS_LEN, 0);
			}
			if (swc == 6)				//索引为RTC时间设置												
			{
				recv_ret = socket_timeout_recv(new_fd, rtc_cmds, SOCKET_RTC_TIME_LEN);
				if (recv_ret == SOCKET_TIMEOUT_ERR) {
					continue;
				} else if ((recv_ret == SOCKET_CLOSE_ERR) ||  (recv_ret == SOCKET_OTHERS_ERR)) {
					break;
				}
			} else if (swc == 7)		//索引为接收配置文件，继续接收										
			{	//先收长度
				recv_ret = socket_timeout_recv(new_fd, sys_rt.json_cfg_file_recv, SOCKET_CONFIG_FILE_HEAD_LEN);
				cfg_file_offset = *(uint32_t *)(sys_rt.json_cfg_file_recv + SOCKET_CONFIG_FILE_OFFSET_OFFSET);
				cfg_file_len = *(uint32_t *)(sys_rt.json_cfg_file_recv + SOCKET_CONFIG_FILE_LEN_OFFSET);
				if (cfg_file_offset != SOCKET_CONFIG_FILE_HEAD_LEN)	// 含有预留信息
				{
					recv_ret = socket_timeout_recv(new_fd, sys_rt.json_resv_file_recv, 
													cfg_file_offset - SOCKET_CONFIG_FILE_HEAD_LEN);
					if (sys_cfg.debug == ON) {
						printf("%s\n", sys_rt.json_resv_file_recv);
						printf("recv json resv file length is %d\n", cfg_file_offset - SOCKET_CONFIG_FILE_HEAD_LEN);
					}
				}
				recv_file_len = 0;
				while (recv_file_len < cfg_file_len)
				{
					recv_ret = socket_timeout_recv(new_fd, sys_rt.json_cfg_file_recv + recv_file_len, 
															SOCKET_RECV_BUF_SIZE);			
					if (recv_ret == SOCKET_TIMEOUT_ERR) {
						break;
					} else if ((recv_ret == SOCKET_CLOSE_ERR) ||  (recv_ret == SOCKET_OTHERS_ERR)) {
						break;
					} else {
						recv_file_len += recv_ret;
					}
					
					if (recv_file_len >= cfg_file_len) {					// 成功接收
						if (sys_cfg.debug == ON) {
							printf("%s\n", sys_rt.json_cfg_file_recv);
							printf("recv json config file length is %d\n", recv_file_len);
						}
						sleep(SOCKET_CFG_FILE_DELAY);						// 防止频繁配置系统
					} else
						continue;
				}
			}
		}

		printf("usr socket cmd is %s, cmd index is %d\n", usr_cmds, swc);

		switch(swc) 
		{
			case 0 :
				acq_start_cmd_exec();
				break;
			case 1 :
				acq_stop_cmd_exec();
				break;
			case 2 :
				tib_start_cmd_exec();
				break;
			case 3 :
				tib_stop_cmd_exec();
				break;
			case 4 :		//重启	
				system_reboot_cmd_exec();
				break;
			case 5 :		//心跳
				system_heartbeat_cmd_exec(s);
				break;
			case 6 :		//时钟同步
				socket_rtc_cmd_parse(s, rtc_cmds);
				break;
			case 7 : 
				socket_json_cfg_file_resv(s, sys_rt.json_cfg_file_recv, cfg_file_len);
				memset(sys_rt.json_cfg_file_recv, 0x00, JSON_CONFIG_FILE_MAX_LEN);
				break;
			case 8 : 	// 获取json config
				socket_json_cfg_with_fd_file_send(s, JSON_CONFIG_FILE);
				break;
			case 9 : case 10 : case 11 : case 12 : case 13 : case 14 : case 15 : case 16 :	//加速度通道
			case 17 : case 18 : case 19 : case 20 : case 21 : case 22 : case 23 : case 24 :
				chx_index = (uint8_t)get_chx_index_from_cmds(usr_cmds);
				vib_single_channel_data_send(s, chx_index, &sys_cfg, spd_rt, chx_cfg, acc_rt, &sys_rt);
				break;
			case 25 : case 26 : 		//速度通道	
				chx_index = get_spd_index_from_cmds(usr_cmds);
				printf("chx_index is %d\n", chx_index);
				speed_channel_data_send(s, chx_index, &sys_cfg, chx_cfg, spd_cfg, spd_rt, &sys_rt);
				break;
			case 27 :											//所有通道状态
				all_channels_state_send(s, &sys_cfg, chx_cfg, acc_rt, spd_cfg, spd_rt, &sys_rt);   
				break;
			case 28 :	// 设备基本信息								
				device_basic_info_send(s, &sys_cfg, chx_cfg, spd_rt, &sys_rt); 
				break;
			case 29 :	// 所有通道数据
				all_channel_data_send(s, &sys_cfg, spd_rt, chx_cfg, acc_rt, spd_cfg, &sys_rt); 
				break;
			case 30 :
				disk_vdata_clear(VDATA_SAVE_HDD1_PATH);
				break;
			case 31 :
				disk_vdata_clear(VDATA_SAVE_HDD2_PATH);
				break;
			case 32 :
				disk_vdata_clear(VDATA_SAVE_EMMC_PATH);
				break;
			case 33 :
				techical_support_info_send(s);
				break;
			default :
				printf("usr socket cmd is %s, cmd absence!\n", usr_cmds);
				dzlog_warn("usr socket cmd is %s, cmd absence!", usr_cmds);
				break;
		}

		signal(SIGPIPE, SIG_IGN);

		usleep(SOCKET_US_DELAY);
	}
	close(new_fd);
	s->status = TS_DETACH;
	dzlog_notice("socket the child thread exiting!");
	printf("socket the child thread exiting!\n");
	pthread_exit((void *)0);
}

